<html><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Chapter 9. Database Testing</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <link rel="stylesheet" href="docbook.css" tppabs="http://www.phpunit.de/manual/current/en/docbook.css" type="text/css"></link>
</head>
<body>

<div id="header">
  <h1>PHPUnit Manual</h1>

  <ul>
<li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.4/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.4/en/index.html'" tppabs="http://www.phpunit.de/manual/3.4/en/index.html">PHPUnit 3.4 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.3/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.3/en/index.html'" tppabs="http://www.phpunit.de/manual/3.3/en/index.html" class="active">PHPUnit 3.3 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.2/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.2/en/index.html'" tppabs="http://www.phpunit.de/manual/3.2/en/index.html">PHPUnit 3.2 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.1/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.1/en/index.html'" tppabs="http://www.phpunit.de/manual/3.1/en/index.html">PHPUnit 3.1 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.0/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.0/en/index.html'" tppabs="http://www.phpunit.de/manual/3.0/en/index.html">PHPUnit 3.0 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/2.3/en/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/2.3/en/index.html'" tppabs="http://www.phpunit.de/manual/2.3/en/index.html">PHPUnit 2.3 <span><small>English</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.3/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.3/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.3/ja/index.html">PHPUnit 3.3 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.2/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.2/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.2/ja/index.html">PHPUnit 3.2 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.1/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.1/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.1/ja/index.html">PHPUnit 3.1 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/3.0/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/3.0/ja/index.html'" tppabs="http://www.phpunit.de/manual/3.0/ja/index.html">PHPUnit 3.0 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/2.3/ja/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/2.3/ja/index.html'" tppabs="http://www.phpunit.de/manual/2.3/ja/index.html">PHPUnit 2.3 <span><small>Japanese</small></span></a></li><li><a href="javascript:if(confirm('http://www.phpunit.de/manual/2.3/de/index.html  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/2.3/de/index.html'" tppabs="http://www.phpunit.de/manual/2.3/de/index.html">PHPUnit 2.3 <span><small>German</small></span></a></li>
  </ul>
</div>
<div class="colmask leftmenu">
  <div class="colleft">
    <div class="col1">
      <table border="0" width="100%">
        <tr>
          <td align="left"><a accesskey="p" href="testcase-extensions.html" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html">Prev</a></td>
          <td align="right"><a accesskey="n" href="incomplete-and-skipped-tests.html" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html">Next</a></td>
        </tr>
      </table>
<div class="chapter" title="Chapter 9. Database Testing"><div class="titlepage"><div><div><h2 class="title"><a id="database"></a>Chapter 9. Database Testing</h2></div></div></div><p>
    <a id="id2559763" class="indexterm"></a>
    <a id="id2559694" class="indexterm"></a>

    While creating tests for your software you may come across database code 
    that needs to be unit tested. The database extension has been created to 
    provide an easy way to place your database in a known state, execute your 
    database-effecting code, and ensure that the expected data is found in the 
    database.
  </p><p>
    The quickest way to create a new Database Unit Test is to extend the 
    <code class="literal">PHPUnit_Extensions_Database_TestCase</code> class. This class 
    provides the functionality to create a database connection, seed your 
    database with data, and after executing a test comparing the contents of 
    your database with a data set that can be built in a variety of formats. In 
    <a class="xref" href="database.html#database.examples.DatabaseTestSetup.php" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.DatabaseTestSetup.php" title="Example 9.1: Setting up a database test case">Example 9.1</a> you can see 
    examples of <code class="literal">getConnection()</code> and <code class="literal">getDataSet()
    </code> implementations.
  </p><div class="example"><a id="database.examples.DatabaseTestSetup.php"></a><p class="title"><b>Example 9.1: Setting up a database test case</b></p><div class="example-contents"><pre class="programlisting"><code><span class="default">&lt;?php</span><br /><span class="keyword">require_once</span><span class="default">&nbsp;</span><span class="string">'PHPUnit/Extensions/Database/TestCase.php'</span><span class="keyword">;</span><br />&nbsp;<br /><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">DatabaseTest</span><span class="default">&nbsp;</span><span class="keyword">extends</span><span class="default">&nbsp;</span><span class="default">PHPUnit_Extensions_Database_TestCase</span><br /><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getConnection</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$pdo</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">PDO</span><span class="keyword">(</span><span class="string">'mysql:host=localhost;dbname=testdb'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'root'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">''</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">createDefaultDBConnection</span><span class="keyword">(</span><span class="default">$pdo</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'testdb'</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getDataSet</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">createFlatXMLDataSet</span><span class="keyword">(</span><span class="default">dirname</span><span class="keyword">(</span><span class="default">__FILE__</span><span class="keyword">)</span><span class="keyword">.</span><span class="string">'/_files/bank-account-seed.xml'</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?&gt;</span><br /></code></pre></div></div><br class="example-break"></br><p>
    The <code class="literal">getConnection()</code> method must return an 
    implementation of the <code class="literal">PHPUnit_Extensions_Database_DB_IDatabaseConnection</code>
    interface. The <code class="literal">createDefaultDBConnection()</code> method can 
    be used to return a database connection. It accepts a <code class="literal">PDO</code> 
    object as the first parameter and the name of the schema you are testing 
    against as the second parameter.
  </p><p>
    The <code class="literal">getDataSet()</code> method must return an implementation of 
    the <code class="literal">PHPUnit_Extensions_Database_DataSet_IDataSet</code> 
    interface. There are currently three different data sets available in 
    PHPUnit. These data sets are discussed in <a class="xref" href="database.html#database.datasets" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets" title="Data Sets">the section called “Data Sets”</a>
  </p><div class="table"><a id="database.tables.testcase.api"></a><p class="title"><b>Table 9.1. Database Test Case Methods</b></p><div class="table-contents"><table summary="Database Test Case Methods" border="1"><colgroup><col></col><col></col></colgroup><thead><tr><th align="left">Method</th><th align="left">Meaning</th></tr></thead><tbody><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_DB_IDatabaseConnection getConnection()</code></td><td align="left">Implement to return the database connection that will be checked for expected data sets and tables.</td></tr><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_DataSet_IDataSet getDataSet()</code></td><td align="left">Implement to return the data set that will be used in in database set up and tear down operations.</td></tr><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_Operation_DatabaseOperation getSetUpOperation()</code></td><td align="left">Override to return a specific operation that should be performed on the test database at the beginning of each test. The various operations are detailed in <a class="xref" href="database.html#database.operations" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.operations" title="Operations">the section called “Operations”</a>.</td></tr><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_Operation_DatabaseOperation getTearDownOperation()</code></td><td align="left">Override to return a specific operation that should be performed on the test database at the end of each test. The various operations are detailed in <a class="xref" href="database.html#database.operations" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.operations" title="Operations">the section called “Operations”</a>.</td></tr><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection createDefaultDBConnection(PDO $connection, string $schema)</code></td><td align="left">Return a database connection wrapper around the <code class="literal">$connection</code> <code class="literal">PDO</code> object. The database schema being tested against should be specified by <code class="literal">$schema</code>. The result of this method can be returned from <code class="literal">getConnection()</code>.</td></tr><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_DataSet_FlatXmlDataSet createFlatXMLDataSet(string $xmlFile)</code></td><td align="left">Returns a flat XML data set that is created from the XML file located at the absolute path specified in <code class="literal">$xmlFile</code>. More details about flat XML files can be found in <a class="xref" href="database.html#database.datasets.flatxml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.flatxml" title="Flat XML Data Set">the section called “Flat XML Data Set”</a>. The result of this method can be returned from <code class="literal">getDataSet()</code>.</td></tr><tr><td align="left"><code class="literal">PHPUnit_Extensions_Database_DataSet_XmlDataSet createXMLDataSet(string $xmlFile)</code></td><td align="left">Returns a XML data set that is created from the XML file located at the absolute path specified in <code class="literal">$xmlFile</code>. More details about XML files can be found in <a class="xref" href="database.html#database.datasets.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.xml" title="XML Data Set">the section called “XML Data Set”</a>. The result of this method can be returned from <code class="literal">getDataSet()</code>.</td></tr><tr><td align="left"><code class="literal">void assertTablesEqual(PHPUnit_Extensions_Database_DataSet_ITable $expected, PHPUnit_Extensions_Database_DataSet_ITable $actual)</code></td><td align="left">Reports an error if the contents of the <code class="literal">$expected</code> table do not match the contents in the <code class="literal">$actual</code> table.</td></tr><tr><td align="left"><code class="literal">void assertDataSetsEqual(PHPUnit_Extensions_Database_DataSet_IDataSet $expected, PHPUnit_Extensions_Database_DataSet_IDataSet $actual)</code></td><td align="left">Reports an error if the contents of the <code class="literal">$expected</code> data set do not match the contents in the <code class="literal">$actual</code> data set.</td></tr></tbody></table></div></div><br class="table-break"></br><div class="section" title="Data Sets"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="database.datasets"></a>Data Sets</h2></div></div></div><p>
      Data sets are the basic building blocks for both your database fixture as 
      well as the assertions you may make at the end of your test. When 
      returning a data set as a fixture from the <code class="literal">PHPUnit_Extensions_Database_TestCase::getDataSet()</code>
      method, the default implementation in PHPUnit will automatically truncate 
      all tables specified and then insert the data from your data set in the 
      order specified by the data set. For your convenience there are several 
      different types of data sets that can be used at your convenience.
    </p><div class="section" title="Flat XML Data Set"><div class="titlepage"><div><div><h3 class="title"><a id="database.datasets.flatxml"></a>Flat XML Data Set</h3></div></div></div><p>
        The flat XML data set is a very simple XML format that uses a single 
        XML element for each row in your data set. An example of a flat XML 
        data set is shown in <a class="xref" href="database.html#database.examples.flatxmldataset.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.flatxmldataset.xml" title="Example 9.2: A Flat XML Data Set">Example 9.2</a>. 
      </p><div class="example"><a id="database.examples.flatxmldataset.xml"></a><p class="title"><b>Example 9.2: A Flat XML Data Set</b></p><div class="example-contents"><pre class="programlisting"><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;dataset&gt;
  &lt;post 
    post_id="1" 
    title="My First Post" 
    date_created="2008-12-01 12:30:29" 
    contents="This is my first post" rating="5"
  /&gt;
  &lt;post 
    post_id="2" 
    title="My Second Post" 
    date_created="2008-12-04 15:35:25" 
    contents="This is my second post" 
  /&gt;
  &lt;post 
    post_id="3" 
    title="My Third Post" 
    date_created="2008-12-09 03:17:05" 
    contents="This is my third post" 
    rating="3" 
  /&gt;

  &lt;post_comment 
    post_comment_id="2" 
    post_id="2" 
    author="Frank" 
    content="That is because this is simply an example." 
    url="http://phpun.it/" 
  /&gt;
  &lt;post_comment 
    post_comment_id="1" 
    post_id="2" 
    author="Tom" 
    content="While the topic seemed interesting the content was lacking." 
  /&gt;

  &lt;current_visitors /&gt;
&lt;/dataset&gt;
</code></pre></div></div><br class="example-break"></br><p>
        As you can see the formatting is extremely simple. Each of the elements 
        within the root <code class="literal">&lt;dataset&gt;</code> element represents a 
        row in the test database with the exception of the last 
        <code class="literal">&lt;current_visitors /&gt;</code> element (this will be 
        discussed shortly.) The name of the element is the equivalent of a 
        table name in your database. The name of each attribute is the 
        equivalent of a column name in your databases. The value of each 
        attribute is the equivalent of the value of that column in that row.
      </p><p>
        This format, while simple, does have some special considerations. The 
        first of these is how you deal with empty tables. With the default 
        operation of <code class="literal">CLEAN_INSERT</code> you can specify that you 
        want to truncate a table and not insert any values by listing that 
        table as an element without any attributes. This can be seen in 
        <a class="xref" href="database.html#database.examples.flatxmldataset.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.flatxmldataset.xml" title="Example 9.2: A Flat XML Data Set">Example 9.2</a> with the 
        <code class="literal">&lt;current_visitors /&gt;</code> element. The most common 
        reason you would want to ensure an empty table as a part of your 
        fixture is when your test should be inserting data to that table. The 
        less data your database has, the quicker your tests will run. So if I 
        where testing my simple blogging software's ability to add comments to 
        a post, I would likely change 
        <a class="xref" href="database.html#database.examples.flatxmldataset.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.flatxmldataset.xml" title="Example 9.2: A Flat XML Data Set">Example 9.2</a> to specify 
        <code class="literal">post_comment</code> as an empty table. When dealing with 
        assertions it is often useful to ensure that a table is not being 
        unexpectedly written to, which could also be accomplished in FlatXML 
        using the empty table format.
      </p><p>
        The second consideration is how <code class="literal">NULL</code> values are 
        defined. The nature of the flat XML format only allows you to 
        explicitly specify strings for column values. Of course your database 
        will convert a string representation of a number or date into the 
        appropriate data type. However, there are no string representations of 
        <code class="literal">NULL</code>. You can imply a <code class="literal">NULL</code> value 
        by leaving a column out of your element's attribute list. This will 
        cause a NULL value to be inserted into the database for that column. 
        This leads me right into my next consideration that makes implicit 
        <code class="literal">NULL</code> values somewhat difficult to deal with.
      </p><p>
        The third consideration is how columns are defined. The column list for 
        a given table is determined by the attributes in the first element for 
        any given table. 
        In <a class="xref" href="database.html#database.examples.flatxmldataset.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.flatxmldataset.xml" title="Example 9.2: A Flat XML Data Set">Example 9.2</a> the 
        <code class="literal">post</code> table would be considered to have the columns 
        <code class="literal">post_id</code>, <code class="literal">title</code>, 
        <code class="literal">date_created</code>, <code class="literal">contents</code> and 
        <code class="literal">rating</code>. If the first <code class="literal">&lt;post&gt;</code> 
        were removed then the <code class="literal">post</code> would no longer be 
        considered to have the rating column. This means that the first element 
        of a given name defines the structure of that table. In the simplest of 
        examples, this means that your first defined row must have a value for 
        every column that you expect to have values for in the rest of rows for 
        that table. If an element further into your data set specifies a column 
        that was not specified in the first element then that value will be 
        ignored. You can see how this influenced the order of elements in my 
        dataset in <a class="xref" href="database.html#database.examples.flatxmldataset.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.flatxmldataset.xml" title="Example 9.2: A Flat XML Data Set">Example 9.2</a>. 
        I had to specify the second <code class="literal">&lt;post_comment&gt;</code> 
        element first due to the non-NULL value in the <code class="literal">url</code> 
        column.
      </p><p>
        There is a way to work around the inability to explicitly set 
        <code class="literal">NULL</code> in a flat XML data using the Replacement data 
        set type. This will be discussed further in 
        <a class="xref" href="database.html#database.datasets.replacement" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.replacement" title="Replacement Data Set">the section called “Replacement Data Set”</a>.
      </p></div><div class="section" title="XML Data Set"><div class="titlepage"><div><div><h3 class="title"><a id="database.datasets.xml"></a>XML Data Set</h3></div></div></div><p>
        While the flat XML data set is simple it also proves to be limiting. A 
        more powerful xml alternative is the XML data set. It is a more 
        structured xml format that allows you to be much more explicit with 
        your data set. An example of the XML data set equivalent to the previous 
        flat XML example is shown in 
        <a class="xref" href="database.html#database.examples.xmldataset.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.xmldataset.xml" title="Example 9.3: A XML Data Set">Example 9.3</a>. 
      </p><div class="example"><a id="database.examples.xmldataset.xml"></a><p class="title"><b>Example 9.3: A XML Data Set</b></p><div class="example-contents"><pre class="programlisting"><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;dataset&gt;
  &lt;table name="post"&gt;
    &lt;column&gt;post_id&lt;/column&gt;
    &lt;column&gt;title&lt;/column&gt;
    &lt;column&gt;date_created&lt;/column&gt;
    &lt;column&gt;contents&lt;/column&gt;
    &lt;column&gt;rating&lt;/column&gt;
    &lt;row&gt;
      &lt;value&gt;1&lt;/value&gt;
      &lt;value&gt;My First Post&lt;/value&gt;
      &lt;value&gt;2008-12-01 12:30:29&lt;/value&gt;
      &lt;value&gt;This is my first post&lt;/value&gt;
      &lt;value&gt;5&lt;/value&gt;
    &lt;/row&gt;
    &lt;row&gt;
      &lt;value&gt;2&lt;/value&gt;
      &lt;value&gt;My Second Post&lt;/value&gt;
      &lt;value&gt;2008-12-04 15:35:25&lt;/value&gt;
      &lt;value&gt;This is my second post&lt;/value&gt;
      &lt;null /&gt;
    &lt;/row&gt;
    &lt;row&gt;
      &lt;value&gt;3&lt;/value&gt;
      &lt;value&gt;My Third Post&lt;/value&gt;
      &lt;value&gt;2008-12-09 03:17:05&lt;/value&gt;
      &lt;value&gt;This is my third post&lt;/value&gt;
      &lt;value&gt;3&lt;/value&gt;
    &lt;/row&gt;
  &lt;/table&gt;
  &lt;table name="post_comment"&gt;
    &lt;column&gt;post_comment_id&lt;/column&gt;
    &lt;column&gt;post_id&lt;/column&gt;
    &lt;column&gt;author&lt;/column&gt;
    &lt;column&gt;content&lt;/column&gt;
    &lt;column&gt;url&lt;/column&gt;
    &lt;row&gt;
      &lt;value&gt;1&lt;/value&gt;
      &lt;value&gt;2&lt;/value&gt;
      &lt;value&gt;Tom&lt;/value&gt;
      &lt;value&gt;While the topic seemed interesting the content was lacking.&lt;/value&gt;
      &lt;null /&gt;
    &lt;/row&gt;
    &lt;row&gt;
      &lt;value&gt;2&lt;/value&gt;
      &lt;value&gt;2&lt;/value&gt;
      &lt;value&gt;Frank&lt;/value&gt;
      &lt;value&gt;That is because this is simply an example.&lt;/value&gt;
      &lt;value&gt;http://phpun.it&lt;/value&gt;
    &lt;/row&gt;
  &lt;/table&gt;
  &lt;table name="current_visitors"&gt;
    &lt;column&gt;current_visitors_id&lt;/column&gt;
    &lt;column&gt;ip&lt;/column&gt;
  &lt;/table&gt;
&lt;/dataset&gt;
</code></pre></div></div><br class="example-break"></br><p>
        The formatting is more verbose than that of the Flat XML data set but 
        in some ways much easier to understand. The root element is again the 
        <code class="literal">&lt;dataset&gt;</code> element. Then directly under that 
        element you will have one or more <code class="literal">&lt;table&gt;</code> 
        elements. Each <code class="literal">&lt;table&gt;</code> element must have a 
        <code class="literal">name</code> attribute with a value equivalent to the name 
        of the table being represented. The <code class="literal">&lt;table&gt;</code> 
        element will then include one or more <code class="literal">&lt;column&gt;</code> 
        elements containing the name of a column in that table. The 
        <code class="literal">&lt;table&gt;</code> element will also include any number 
        (including zero) of <code class="literal">&lt;row&gt;</code> elements. The 
        <code class="literal">&lt;row&gt;</code> element will be what ultimately 
        specifies the data to store/remove/update in the database or to check 
        the current database against. The <code class="literal">&lt;row&gt;</code> 
        element must have the same number of children as there are 
        <code class="literal">&lt;column&gt;</code> elements in that 
        <code class="literal">&lt;table&gt;</code> element. The order of your child 
        elements is also determined by the order of your 
        <code class="literal">&lt;column&gt;</code> elements for that table. There are 
        two different elements that can be used as children of the 
        <code class="literal">&lt;row&gt;</code> element. You may use the 
        <code class="literal">&lt;value&gt;</code> element to specify the value of that 
        column in much the same way you can use attributes in the flat XML data 
        set. The content of the <code class="literal">&lt;value&gt;</code> element will 
        be considered the content of that column for that row. You may also use 
        the <code class="literal">&lt;null&gt;</code> element to explicitly indicate 
        that the column is to be given a <code class="literal">NULL</code> value. The 
        <code class="literal">&lt;null&gt;</code> element does not contain any attributes 
        or children.
      </p><p>
        You can use the DTD in 
        <a class="xref" href="database.html#database.examples.xmldatasetdtd.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.xmldatasetdtd.xml" title="Example 9.4: The XML Data Set DTD">Example 9.4</a> to validate your 
        XML data set files. A reference of the valid elements in an XML data 
        set can be found in <a class="xref" href="database.html#database.tables.xmldataset.elements" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.tables.xmldataset.elements" title="Table 9.2. XML Data Set Element Description">Table 9.2</a>
      </p><div class="example"><a id="database.examples.xmldatasetdtd.xml"></a><p class="title"><b>Example 9.4: The XML Data Set DTD</b></p><div class="example-contents"><pre class="programlisting"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!ELEMENT dataset (table+) | ANY&gt;
&lt;!ELEMENT table (column*, row*)&gt;
&lt;!ATTLIST table
    name CDATA #REQUIRED
&gt;
&lt;!ELEMENT column (#PCDATA)&gt;
&lt;!ELEMENT row (value | null | none)*&gt;
&lt;!ELEMENT value (#PCDATA)&gt;
&lt;!ELEMENT null EMPTY&gt;
</code></pre></div></div><br class="example-break"></br><div class="table"><a id="database.tables.xmldataset.elements"></a><p class="title"><b>Table 9.2. XML Data Set Element Description</b></p><div class="table-contents"><table summary="XML Data Set Element Description" border="1"><colgroup><col></col><col></col><col></col><col></col></colgroup><thead><tr><th align="left">Element</th><th align="left">Purpose</th><th align="left">Contents</th><th align="left">Attributes</th></tr></thead><tbody><tr><td align="left"><code class="literal">&lt;dataset&gt;</code></td><td align="left">The root element of the xml data set file.</td><td align="left">One or more <code class="literal">&lt;table&gt;</code> elements.</td><td align="left">None</td></tr><tr><td align="left"><code class="literal">&lt;table&gt;</code></td><td align="left">Defines a table in the dataset.</td><td align="left">One or more <code class="literal">&lt;column&gt;</code> elements and zero or more <code class="literal">&lt;row&gt;</code> elements.</td><td align="left"><code class="literal">name</code> - The name of the table.</td></tr><tr><td align="left"><code class="literal">&lt;column&gt;</code></td><td align="left">Defines a column in the current table.</td><td align="left">A text node containing the name of the column.</td><td align="left">None</td></tr><tr><td align="left"><code class="literal">&lt;row&gt;</code></td><td align="left">Defines a row in the table.</td><td align="left">One or more <code class="literal">&lt;value&gt;</code> or <code class="literal">&lt;null&gt;</code> elements.</td><td align="left">None</td></tr><tr><td align="left"><code class="literal">&lt;value&gt;</code></td><td align="left">Sets the value of the column in the same position as this value.</td><td align="left">A text node containing the value of the corresponding column.</td><td align="left">None</td></tr><tr><td align="left"><code class="literal">&lt;null&gt;</code></td><td align="left">Sets the value of the column in the same position of this value to <code class="literal">NULL</code>.</td><td align="left">None</td><td align="left">None</td></tr></tbody></table></div></div><br class="table-break"></br></div><div class="section" title="CSV Data Set"><div class="titlepage"><div><div><h3 class="title"><a id="database.datasets.csv"></a>CSV Data Set</h3></div></div></div><p>
        While XML data sets provide a convenient way to structure your data, in many cases they can be time consuming to hand edit as there are not very many XML editors that provide an easy way to edit tabular data via xml. In these cases you may find the CSV data set to be much more useful. The CSV data set is very simple to understand. Each CSV file represents a table. The first row in the CSV file must contain the column names and all subsequent rows will contain the data for those columns.
      </p><p>
        To construct a CSV data set you must instantiate the <code class="literal">PHPUnit_Extensions_Database_DataSet_CsvDataSet</code> class. The constructor takes three parameters: <code class="literal">$delimiter</code>, <code class="literal">$enclosure</code> and <code class="literal">$escape</code>. These parameters allow you to specify the exact formatting of rows within your CSV file. So this of course means it doesn't have to really be a CSV file. You can also provide a tab delimited file. The default constructor will specify a comma delimited file with fields enclosed by a double quote. If there is a double quote within a value it will be escaped by an additional double quote. This is as close to an accepted standard for CSV as there is.
      </p><p>
        Once your CSV data set class is instantiated you can use the method <code class="literal">addTable()</code> to add CSV files as tables to your data set. The <code class="literal">addTable</code> method takes two parameters. The first is <code class="literal">$tableName</code> and contains the name of the table you are adding. The second is <code class="literal">$csvFile</code> and contains the path to the CSV you will be using to set the data for that table. You can call <code class="literal">addTable()</code> for each table you would like to add to your data set.
      </p><p>
        In <a class="xref" href="database.html#database.examples.csvdataset" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.examples.csvdataset" title="Example 9.5: CSV Data Set Example">Example 9.5</a> you can see an example of how three CSV files can be combined into the database fixture for a database test case.
      </p><div class="example"><a id="database.examples.csvdataset"></a><p class="title"><b>Example 9.5: CSV Data Set Example</b></p><div class="example-contents"><pre class="programlisting"><code>&nbsp;<br /><span class="html">---&nbsp;fixture/post.csv&nbsp;---</span><br /><span class="html">post_id,title,date_created,contents,rating</span><br /><span class="html">1,My&nbsp;First&nbsp;Post,2008-12-01&nbsp;12:30:29,This&nbsp;is&nbsp;my&nbsp;first&nbsp;post,5</span><br /><span class="html">2,My&nbsp;Second&nbsp;Post,2008-12-04&nbsp;15:35:25,This&nbsp;is&nbsp;my&nbsp;second&nbsp;post,</span><br /><span class="html">3,My&nbsp;Third&nbsp;Post,2008-12-09&nbsp;03:17:05,This&nbsp;is&nbsp;my&nbsp;third&nbsp;post,3</span><br />&nbsp;<br /><span class="html">---&nbsp;fixture/post_comment.csv&nbsp;---</span><br /><span class="html">post_comment_id,post_id,author,content,url</span><br /><span class="html">1,2,Tom,While&nbsp;the&nbsp;topic&nbsp;seemed&nbsp;interesting&nbsp;the&nbsp;content&nbsp;was&nbsp;lacking.,</span><br /><span class="html">2,2,</span><span class="html">Frank,That&nbsp;is&nbsp;because&nbsp;this&nbsp;is&nbsp;simply&nbsp;an&nbsp;example.,http://phpun.it</span><br />&nbsp;<br /><span class="html">---&nbsp;fixture/current_visitors.csv&nbsp;---</span><br /><span class="html">current_visitors_id,ip</span><br />&nbsp;<br /><span class="html">---&nbsp;DatabaseTest.php&nbsp;---</span><br /><span class="default">&lt;?php</span><br /><span class="keyword">require_once</span><span class="default">&nbsp;</span><span class="string">'PHPUnit/Extensions/Database/TestCase.php'</span><span class="keyword">;</span><br /><span class="keyword">require_once</span><span class="default">&nbsp;</span><span class="string">'PHPUnit/Extensions/Database/DataSet/CsvDataSet.php'</span><span class="keyword">;</span><br />&nbsp;<br /><span class="keyword">class</span><span class="default">&nbsp;</span><span class="default">DatabaseTest</span><span class="default">&nbsp;</span><span class="keyword">extends</span><span class="default">&nbsp;</span><span class="default">PHPUnit_Extensions_Database_TestCase</span><br /><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getConnection</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$pdo</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">PDO</span><span class="keyword">(</span><span class="string">'mysql:host=localhost;dbname=testdb'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'root'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">''</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$this</span><span class="keyword">-&gt;</span><span class="default">createDefaultDBConnection</span><span class="keyword">(</span><span class="default">$pdo</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'testdb'</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br />&nbsp;<br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span class="default">&nbsp;</span><span class="keyword">function</span><span class="default">&nbsp;</span><span class="default">getDataSet</span><span class="keyword">(</span><span class="keyword">)</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">{</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$dataSet</span><span class="default">&nbsp;</span><span class="keyword">=</span><span class="default">&nbsp;</span><span class="keyword">new</span><span class="default">&nbsp;</span><span class="default">PHPUnit_Extensions_Database_DataSet_CsvDataSet</span><span class="keyword">(</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$dataSet</span><span class="keyword">-&gt;</span><span class="default">addTable</span><span class="keyword">(</span><span class="string">'post'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'fixture/post.csv'</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$dataSet</span><span class="keyword">-&gt;</span><span class="default">addTable</span><span class="keyword">(</span><span class="string">'post_comment'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'fixture/post_comment.csv'</span><span class="keyword">)</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="default">$dataSet</span><span class="keyword">-&gt;</span><span class="default">addTable</span><span class="keyword">(</span><span class="string">'current_visitors'</span><span class="keyword">,</span><span class="default">&nbsp;</span><span class="string">'fixture/current_visitors.csv'</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span class="default">&nbsp;</span><span class="default">$dataSet</span><span class="keyword">;</span><br /><span class="default">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">}</span><br /><span class="keyword">}</span><br /><span class="default">?&gt;</span><br /></code></pre></div></div><br class="example-break"></br><p>
        Unfortunately, while the CSV dataset is appealing from the aspect of edit-ability, it has the same problems with <code class="literal">NULL</code> values as the flat XML dataset. There is no native way to explicitly specify a null value. If you do not specify a value (as I have done with some of the fields above) then the value will actually be set to that data type's equivalent of an empty string. Which in most cases will not be what you want. I will address this shortcoming of both the CSV and the flat XML data sets shortly.
      </p></div><div class="section" title="Replacement Data Set"><div class="titlepage"><div><div><h3 class="title"><a id="database.datasets.replacement"></a>Replacement Data Set</h3></div></div></div><p>
        ...
      </p></div></div><div class="section" title="Operations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="database.operations"></a>Operations</h2></div></div></div><p>
      ...
    </p></div><div class="section" title="Database Testing Best Practices"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="database.bestpractices"></a>Database Testing Best Practices</h2></div></div></div><p>
      ...
    </p></div></div>
      <table border="0" width="100%">
        <tr>
          <td align="left"><a accesskey="p" href="testcase-extensions.html" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html">Prev</a></td>
          <td align="right"><a accesskey="n" href="incomplete-and-skipped-tests.html" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html">Next</a></td>
        </tr>
      </table>
    </div>
    <div class="col2">
<dl><dt><span class="chapter"><a href="automating-tests.html" tppabs="http://www.phpunit.de/manual/current/en/automating-tests.html">1. 自动化测试</a></span></dt><dt><span class="chapter"><a href="goals.html" tppabs="http://www.phpunit.de/manual/current/en/goals.html">2. PHPUnit的目标</a></span></dt><dt><span class="chapter"><a href="installation.html" tppabs="http://www.phpunit.de/manual/current/en/installation.html">3. 安装PHPUnit</a></span></dt><dt><span class="chapter"><a href="writing-tests-for-phpunit.html" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html">4. 为PHPUnit编写测试</a></span></dt><dd><dl><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers">Data Providers</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.exceptions" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.exceptions">Testing Exceptions</a></span></dt><dt><span class="section"><a href="writing-tests-for-phpunit.html#writing-tests-for-phpunit.errors" tppabs="http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.errors">Testing PHP Errors</a></span></dt></dl></dd><dt><span class="chapter"><a href="textui.html" tppabs="http://www.phpunit.de/manual/current/en/textui.html">5. The Command-Line Test Runner</a></span></dt><dt><span class="chapter"><a href="fixtures.html" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html">6. Fixtures</a></span></dt><dd><dl><dt><span class="section"><a href="fixtures.html#fixtures.more-setup-than-teardown" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.more-setup-than-teardown">More setUp() than tearDown()</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.variations" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.variations">Variations</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.sharing-fixture" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.sharing-fixture">Sharing Fixture</a></span></dt><dt><span class="section"><a href="fixtures.html#fixtures.global-state" tppabs="http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.global-state">Global State</a></span></dt></dl></dd><dt><span class="chapter"><a href="organizing-tests.html" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html">7. Organizing Tests</a></span></dt><dd><dl><dt><span class="section"><a href="organizing-tests.html#organizing-tests.filesystem" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.filesystem">Composing a Test Suite Using the Filesystem</a></span></dt><dt><span class="section"><a href="organizing-tests.html#organizing-tests.xml-configuration" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.xml-configuration">Composing a Test Suite Using XML Configuration</a></span></dt><dt><span class="section"><a href="organizing-tests.html#organizing-tests.testsuite" tppabs="http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.testsuite">Using the TestSuite Class</a></span></dt></dl></dd><dt><span class="chapter"><a href="testcase-extensions.html" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html">8. TestCase Extensions</a></span></dt><dd><dl><dt><span class="section"><a href="testcase-extensions.html#testcase-extensions.output" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html#testcase-extensions.output">Testing Output</a></span></dt><dt><span class="section"><a href="testcase-extensions.html#testcase-extensions.performance" tppabs="http://www.phpunit.de/manual/current/en/testcase-extensions.html#testcase-extensions.performance">Testing Performance</a></span></dt></dl></dd><dt><span class="chapter"><a href="database.html" tppabs="http://www.phpunit.de/manual/current/en/database.html" class="active">9. Database Testing</a></span></dt><dd><dl><dt><span class="section"><a href="database.html#database.datasets" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets">Data Sets</a></span></dt><dd><dl><dt><span class="section"><a href="database.html#database.datasets.flatxml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.flatxml">Flat XML Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.xml" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.xml">XML Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.csv" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.csv">CSV Data Set</a></span></dt><dt><span class="section"><a href="database.html#database.datasets.replacement" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.datasets.replacement">Replacement Data Set</a></span></dt></dl></dd><dt><span class="section"><a href="database.html#database.operations" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.operations">Operations</a></span></dt><dt><span class="section"><a href="database.html#database.bestpractices" tppabs="http://www.phpunit.de/manual/current/en/database.html#database.bestpractices">Database Testing Best Practices</a></span></dt></dl></dd><dt><span class="chapter"><a href="incomplete-and-skipped-tests.html" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html">10. Incomplete and Skipped Tests</a></span></dt><dd><dl><dt><span class="section"><a href="incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.incomplete-tests" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.incomplete-tests">Incomplete Tests</a></span></dt><dt><span class="section"><a href="incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.skipping-tests" tppabs="http://www.phpunit.de/manual/current/en/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests.skipping-tests">Skipping Tests</a></span></dt></dl></dd><dt><span class="chapter"><a href="test-doubles.html" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html">11. Test Doubles</a></span></dt><dd><dl><dt><span class="section"><a href="test-doubles.html#test-doubles.stubs" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs">Stubs</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.mock-objects" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects">Mock Objects</a></span></dt><dt><span class="section"><a href="test-doubles.html#test-doubles.mocking-the-filesystem" tppabs="http://www.phpunit.de/manual/current/en/test-doubles.html#test-doubles.mocking-the-filesystem">Mocking the Filesystem</a></span></dt></dl></dd><dt><span class="chapter"><a href="testing-practices.html" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html">12. Testing Practices</a></span></dt><dd><dl><dt><span class="section"><a href="testing-practices.html#testing-practices.during-development" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html#testing-practices.during-development">During Development</a></span></dt><dt><span class="section"><a href="testing-practices.html#testing-practices.during-debugging" tppabs="http://www.phpunit.de/manual/current/en/testing-practices.html#testing-practices.during-debugging">During Debugging</a></span></dt></dl></dd><dt><span class="chapter"><a href="test-driven-development.html" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html">13. Test-Driven Development</a></span></dt><dd><dl><dt><span class="section"><a href="test-driven-development.html#test-driven-development.bankaccount-example" tppabs="http://www.phpunit.de/manual/current/en/test-driven-development.html#test-driven-development.bankaccount-example">BankAccount Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="behaviour-driven-development.html" tppabs="http://www.phpunit.de/manual/current/en/behaviour-driven-development.html">14. Behaviour-Driven Development</a></span></dt><dd><dl><dt><span class="section"><a href="behaviour-driven-development.html#behaviour-driven-development.bowlinggame-example" tppabs="http://www.phpunit.de/manual/current/en/behaviour-driven-development.html#behaviour-driven-development.bowlinggame-example">BowlingGame Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="code-coverage-analysis.html" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html">15. Code Coverage Analysis</a></span></dt><dd><dl><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.specifying-covered-methods" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html#code-coverage-analysis.specifying-covered-methods">Specifying Covered Methods</a></span></dt><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.ignoring-code-blocks" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html#code-coverage-analysis.ignoring-code-blocks">Ignoring Code Blocks</a></span></dt><dt><span class="section"><a href="code-coverage-analysis.html#code-coverage-analysis.including-excluding-files" tppabs="http://www.phpunit.de/manual/current/en/code-coverage-analysis.html#code-coverage-analysis.including-excluding-files">Including and Excluding Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="other-uses-for-tests.html" tppabs="http://www.phpunit.de/manual/current/en/other-uses-for-tests.html">16. Other Uses for Tests</a></span></dt><dd><dl><dt><span class="section"><a href="other-uses-for-tests.html#other-uses-for-tests.agile-documentation" tppabs="http://www.phpunit.de/manual/current/en/other-uses-for-tests.html#other-uses-for-tests.agile-documentation">Agile Documentation</a></span></dt><dt><span class="section"><a href="other-uses-for-tests.html#other-uses-for-tests.cross-team-tests" tppabs="http://www.phpunit.de/manual/current/en/other-uses-for-tests.html#other-uses-for-tests.cross-team-tests">Cross-Team Tests</a></span></dt></dl></dd><dt><span class="chapter"><a href="skeleton-generator.html" tppabs="http://www.phpunit.de/manual/current/en/skeleton-generator.html">17. Skeleton Generator</a></span></dt><dd><dl><dt><span class="section"><a href="skeleton-generator.html#skeleton-generator.test" tppabs="http://www.phpunit.de/manual/current/en/skeleton-generator.html#skeleton-generator.test">Generating a Test Case Class Skeleton</a></span></dt><dt><span class="section"><a href="skeleton-generator.html#skeleton-generator.class" tppabs="http://www.phpunit.de/manual/current/en/skeleton-generator.html#skeleton-generator.class">Generating a Class Skeleton from a Test Case Class</a></span></dt></dl></dd><dt><span class="chapter"><a href="javascript:if(confirm('http://www.phpunit.de/manual/current/en/selenium.html  \n\nļδ Teleport Pro ȡأΪ ޷ȡãȡغĿֹ̫ͣ졣  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/current/en/selenium.html'" tppabs="http://www.phpunit.de/manual/current/en/selenium.html">18. PHPUnit and Selenium</a></span></dt><dd><dl><dt><span class="section"><a href="javascript:if(confirm('http://www.phpunit.de/manual/current/en/selenium.html  \n\nļδ Teleport Pro ȡأΪ ޷ȡãȡغĿֹ̫ͣ졣  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/current/en/selenium.html#selenium.selenium-rc'" tppabs="http://www.phpunit.de/manual/current/en/selenium.html#selenium.selenium-rc">Selenium RC</a></span></dt><dt><span class="section"><a href="javascript:if(confirm('http://www.phpunit.de/manual/current/en/selenium.html  \n\nļδ Teleport Pro ȡأΪ ޷ȡãȡغĿֹ̫ͣ졣  \n\nҪӷϴ'))window.location='http://www.phpunit.de/manual/current/en/selenium.html#selenium.seleniumtestcase'" tppabs="http://www.phpunit.de/manual/current/en/selenium.html#selenium.seleniumtestcase">PHPUnit_Extensions_SeleniumTestCase</a></span></dt></dl></dd><dt><span class="chapter"><a href="logging.html" tppabs="http://www.phpunit.de/manual/current/en/logging.html">19. Logging</a></span></dt><dd><dl><dt><span class="section"><a href="logging.html#logging.xml" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.xml">Test Results (XML)</a></span></dt><dt><span class="section"><a href="logging.html#logging.tap" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.tap">Test Results (TAP)</a></span></dt><dt><span class="section"><a href="logging.html#logging.json" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.json">Test Results (JSON)</a></span></dt><dt><span class="section"><a href="logging.html#logging.codecoverage" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.codecoverage">Code Coverage (XML)</a></span></dt><dt><span class="section"><a href="logging.html#logging.database" tppabs="http://www.phpunit.de/manual/current/en/logging.html#logging.database">Test Database</a></span></dt></dl></dd><dt><span class="chapter"><a href="build-automation.html" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html">20. Build Automation</a></span></dt><dd><dl><dt><span class="section"><a href="build-automation.html#build-automation.ant" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html#build-automation.ant">Apache Ant</a></span></dt><dt><span class="section"><a href="build-automation.html#build-automation.maven" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html#build-automation.maven">Apache Maven</a></span></dt><dt><span class="section"><a href="build-automation.html#build-automation.phing" tppabs="http://www.phpunit.de/manual/current/en/build-automation.html#build-automation.phing">Phing</a></span></dt></dl></dd><dt><span class="chapter"><a href="continuous-integration.html" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html">21. Continuous Integration</a></span></dt><dd><dl><dt><span class="section"><a href="continuous-integration.html#continuous-integration.atlassian-bamboo" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html#continuous-integration.atlassian-bamboo">Atlassian Bamboo</a></span></dt><dt><span class="section"><a href="continuous-integration.html#continuous-integration.cruisecontrol" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html#continuous-integration.cruisecontrol">CruiseControl</a></span></dt><dt><span class="section"><a href="continuous-integration.html#continuous-integration.phpUnderControl" tppabs="http://www.phpunit.de/manual/current/en/continuous-integration.html#continuous-integration.phpUnderControl">phpUnderControl</a></span></dt></dl></dd><dt><span class="chapter"><a href="api.html" tppabs="http://www.phpunit.de/manual/current/en/api.html">22. PHPUnit API</a></span></dt><dd><dl><dt><span class="section"><a href="api.html#api.overview" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.overview">Overview</a></span></dt><dt><span class="section"><a href="api.html#api.assert" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert">PHPUnit_Framework_Assert</a></span></dt><dd><dl><dt><span class="section"><a href="api.html#api.assert.assertArrayHasKey" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertArrayHasKey"><code class="literal">assertArrayHasKey()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertClassHasAttribute" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertClassHasAttribute"><code class="literal">assertClassHasAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertClassHasStaticAttribute" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertClassHasStaticAttribute"><code class="literal">assertClassHasStaticAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertContains" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertContains"><code class="literal">assertContains()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertContainsOnly" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertContainsOnly"><code class="literal">assertContainsOnly()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertEqualXMLStructure" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertEqualXMLStructure"><code class="literal">assertEqualXMLStructure()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertEquals" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertEquals"><code class="literal">assertEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFalse" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertFalse"><code class="literal">assertFalse()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFileEquals" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertFileEquals"><code class="literal">assertFileEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertFileExists" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertFileExists"><code class="literal">assertFileExists()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertGreaterThan" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertGreaterThan"><code class="literal">assertGreaterThan()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertGreaterThanOrEqual" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertGreaterThanOrEqual"><code class="literal">assertGreaterThanOrEqual()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertLessThan" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertLessThan"><code class="literal">assertLessThan()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertLessThanOrEqual" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertLessThanOrEqual"><code class="literal">assertLessThanOrEqual()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertNotNull" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertNotNull"><code class="literal">assertNotNull()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertObjectHasAttribute" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertObjectHasAttribute"><code class="literal">assertObjectHasAttribute()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertRegExp" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertRegExp"><code class="literal">assertRegExp()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSame" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSame"><code class="literal">assertSame()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectCount" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSelectCount"><code class="literal">assertSelectCount()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectEquals" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSelectEquals"><code class="literal">assertSelectEquals()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertSelectRegExp" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertSelectRegExp"><code class="literal">assertSelectRegExp()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertStringEqualsFile" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertStringEqualsFile"><code class="literal">assertStringEqualsFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertTag" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertTag"><code class="literal">assertTag()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertThat" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertThat"><code class="literal">assertThat()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertTrue" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertTrue"><code class="literal">assertTrue()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertType" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertType"><code class="literal">assertType()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlFileEqualsXmlFile" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertXmlFileEqualsXmlFile"><code class="literal">assertXmlFileEqualsXmlFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlStringEqualsXmlFile" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertXmlStringEqualsXmlFile"><code class="literal">assertXmlStringEqualsXmlFile()</code></a></span></dt><dt><span class="section"><a href="api.html#api.assert.assertXmlStringEqualsXmlString" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.assert.assertXmlStringEqualsXmlString"><code class="literal">assertXmlStringEqualsXmlString()</code></a></span></dt></dl></dd><dt><span class="section"><a href="api.html#api.test" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.test">PHPUnit_Framework_Test</a></span></dt><dt><span class="section"><a href="api.html#api.testcase" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.testcase">PHPUnit_Framework_TestCase</a></span></dt><dt><span class="section"><a href="api.html#api.testsuite" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.testsuite">PHPUnit_Framework_TestSuite</a></span></dt><dt><span class="section"><a href="api.html#api.testresult" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.testresult">PHPUnit_Framework_TestResult</a></span></dt><dt><span class="section"><a href="api.html#api.package-structure" tppabs="http://www.phpunit.de/manual/current/en/api.html#api.package-structure">Package Structure</a></span></dt></dl></dd><dt><span class="chapter"><a href="extending-phpunit.html" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html">23. Extending PHPUnit</a></span></dt><dd><dl><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestCase" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestCase">Subclass PHPUnit_Framework_TestCase</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.Assert" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.Assert">Assert Classes</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Extensions_TestDecorator" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Extensions_TestDecorator">Subclass PHPUnit_Extensions_TestDecorator</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_Test" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_Test">Implement PHPUnit_Framework_Test</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestResult" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestResult">Subclass PHPUnit_Framework_TestResult</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener">Implement PHPUnit_Framework_TestListener</a></span></dt><dt><span class="section"><a href="extending-phpunit.html#extending-phpunit.TestRunner" tppabs="http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.TestRunner">New Test Runner</a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.assertions.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.assertions.html">A. Assertions</a></span></dt><dt><span class="appendix"><a href="appendixes.configuration.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html">B. The XML Configuration File</a></span></dt><dd><dl><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.phpunit" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.phpunit">PHPUnit</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.testsuite" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.testsuite">Test Suite</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.groups" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.groups">Groups</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.blacklist-whitelist" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.blacklist-whitelist">Including and Excluding Files for Code Coverage</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.logging" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.logging">Logging</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.php-ini-constants-variables">Setting PHP INI settings, Constants and Global Variables</a></span></dt><dt><span class="section"><a href="appendixes.configuration.html#appendixes.configuration.selenium-rc" tppabs="http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.selenium-rc">Configuring Browsers for Selenium RC</a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.index.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.index.html">C. Index</a></span></dt><dd><dl><dt><span class="index"><a href="appendixes.index.html#appendixes.index.index" tppabs="http://www.phpunit.de/manual/current/en/appendixes.index.html#appendixes.index.index"></a></span></dt></dl></dd><dt><span class="appendix"><a href="appendixes.bibliography.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.bibliography.html">D. Bibliography</a></span></dt><dt><span class="appendix"><a href="appendixes.copyright.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.copyright.html">E. Copyright</a></span></dt></dl>
    </div>
  </div>
</div>
<div id="footer">
  <p><a href="appendixes.copyright.html" tppabs="http://www.phpunit.de/manual/current/en/appendixes.copyright.html">Copyright</a> &copy; 2005-2009 <a href="javascript:if(confirm('http://sebastian-bergmann.de/  \n\nļδ Teleport Pro ȡأΪ ·ʼַõķΧ  \n\nҪӷϴ'))window.location='http://sebastian-bergmann.de/'" tppabs="http://sebastian-bergmann.de/">Sebastian Bergmann</a>.</p>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www./");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-68261-7");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

